package edu.bu.cs673.superkids123.children.view.games;

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;

import edu.bu.cs673.superkids123.AbstractFrame;
import edu.bu.cs673.superkids123.AbstractNavigationView;
import edu.bu.cs673.superkids123.children.controller.games.NumberMatchingGameController;
import edu.bu.cs673.superkids123.children.model.resources.ChildrenResource;
import edu.bu.cs673.superkids123.children.model.resources.ChildrenResourceProvider;

/**
 * NumberMatchingGameView
 * 
 * View component for the MVC pattern which displays the Number Matching Game.
 * The game deepens a child's understanding of counting by testing their
 * aptitude with a "fun" quiz of matching a number image with a selection of 
 * colored balls. One of the selections is correct. The child can select the
 * number image to hear the number spoken. 
 * 
 * @author David Bardwell
 *
 */
public class NumberMatchingGameView extends AbstractNavigationView implements ActionListener {
	
	public static final int NUMBER_OF_ANSWER_CHOICES = 5;
	public static final int DIAMETER = 25;
	public static final int NUMBER_MODE = 1;
	public static final int IMAGE_MODE = 2;
	
	private boolean readyToPaint = false;
	private JPanel matchingGamePanel;
	private JPanel answerPanel;
	private JPanel graphicsPanel;
	private JButton numberImageButton;
	private JPanel buttonNumberPanel;
	private JButton graphicImageButton;
	private JLabel messageLabel;
	private AnswerButton numberAnswerChoiceButtons[];
	private AnswerButton imageAnswerChoiceButtons[];
	private int[] possibleAnswers;
	private int gameMode;
	ChildrenResourceProvider provider = ChildrenResourceProvider.getInstance();
	private NumberMatchingGameController controller;
	
	public NumberMatchingGameView(AbstractFrame mainFrame) {
		super(mainFrame);
	}

	@Override
	public String getTitle() {
		return "Number Matching Game";
	}

	@Override
	public String getBorderTitle() {
		return "Matching Game";
	}

	/**
	 * @wbp.parser.entryPoint
	 */
	@Override
	protected JComponent layout() {
		
		this.setAvatarVisible(true);
		this.setParentsButtonVisible(false);
		
		matchingGamePanel = new JPanel() {
			private static final long serialVersionUID = 1L;

			// Override paint to show possible answers for the matching number image
			public void paint(Graphics g) {
				super.paint(g);
				if (readyToPaint) {
					int positionX = NumberMatchingGameView.this.answerPanel.getLocation().x;
					int positionY = NumberMatchingGameView.this.answerPanel.getLocation().y;
					Color[] colors = new Color[] {Color.GREEN, Color.ORANGE, Color.BLUE, Color.RED, Color.MAGENTA};
					
					positionX += NumberMatchingGameView.this.numberAnswerChoiceButtons[0].getWidth() + 10 + 20;
					positionY += 10;
					
					// draw next to second, third, fourth and fifth button choice
					for (int i = 0; i < NUMBER_OF_ANSWER_CHOICES; i++) {
						int startingX = positionX;
				        g.setColor(colors[i]);
					    for (int j = 1; j <= possibleAnswers[i]; j++) {
					    	g.drawOval(startingX, positionY, DIAMETER, DIAMETER);
					        g.fillOval(startingX, positionY, DIAMETER, DIAMETER);
					        startingX += 40;
					    }
						positionY += NumberMatchingGameView.this.numberAnswerChoiceButtons[0].getHeight() + 4;
					}    
				}
			}
		};
		
		// Reset to first question if user goes into this game more than once.
		controller = getMainFrame().getController(NumberMatchingGameController.class);
		ImageIcon numberImage = controller.getNumberImage();
		possibleAnswers = controller.getPossibleNumberAnswers();
		ImageIcon graphicImage = controller.getGraphicImage();
		
		// layout consists of a number image (1 to 10) on the left with answers shown as
		// choices of A, B, C, D, or E to the right. The graphical circles are displayed
		// to the right of each choice. One of the answers is the correct one. 
		matchingGamePanel.setLayout(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();
		c.gridx = 0;
		c.gridy = 0;
		c.gridwidth = 1;
		c.gridheight = 1;
		c.weightx = 0;
		c.weighty = 1;
		c.anchor = GridBagConstraints.NORTHWEST;
		c.insets = new Insets(1, 5, 1, 5);
		c.fill = GridBagConstraints.BOTH;
		
		numberImageButton = new JButton();
		int width = numberImage.getIconWidth();
		int height = numberImage.getIconHeight();
		numberImageButton.setBounds(new Rectangle(width, height));		
		numberImageButton.setIcon(numberImage);
		
		graphicImageButton = new JButton();
		width = graphicImage.getIconWidth();
		height = graphicImage.getIconHeight();
		graphicImageButton.setBounds(new Rectangle(width, height));
		graphicImageButton.setIcon(graphicImage);
		
		
		answerPanel = constructAnswerSelectionPanel();
		graphicsPanel = constructGraphicsPanel();
		
		buttonNumberPanel = constructButtonPanel();
		
		// add number image button to panel
		c.gridheight = 5;
		matchingGamePanel.add(numberImageButton, c.clone());
		
		// also, add graphic image button to panel in same place
		matchingGamePanel.add(graphicImageButton, c.clone());
		
		c.gridx = 1;
		c.gridheight = 6;
		matchingGamePanel.add(answerPanel, c.clone());
		
		c.weightx = 1.0;
		c.gridwidth = 2;
		matchingGamePanel.add(buttonNumberPanel, c.clone());
		
		
		c.gridx = 2;
		c.weightx = 1;
		c.gridwidth = 1;
		matchingGamePanel.add(graphicsPanel, c.clone());
		
		
		c.gridy += 6;
		c.gridx = 0;
		c.gridwidth = 3;
		c.gridheight = 1;
		c.weightx = 1;
		c.anchor = GridBagConstraints.SOUTH;
		
		messageLabel = new JLabel("Select the correct answer");
		matchingGamePanel.add(messageLabel, c);
		
		numberImageButton.addActionListener(this);
		
		// initially, graphic is invisible
		graphicImageButton.setVisible(false);
		buttonNumberPanel.setVisible(false);
		
		readyToPaint = true;
		gameMode = NUMBER_MODE;
		return matchingGamePanel;
	}
	
	private JPanel constructAnswerSelectionPanel() {
		JPanel answerPanel = new JPanel();
		answerPanel.setLayout(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();
		c.gridx = 0;
		c.gridy = 0;
		c.gridwidth = 1;
		c.gridheight = 1;
		c.weightx = 1;
		c.weighty = 1;
		c.anchor = GridBagConstraints.NORTH;
		c.insets = new Insets(2, 10, 2, 5);
		c.fill = GridBagConstraints.BOTH;
		
		String buttonLabels = "ABCDEF";
		numberAnswerChoiceButtons = new AnswerButton[NUMBER_OF_ANSWER_CHOICES];
		for (int i = 0; i < NUMBER_OF_ANSWER_CHOICES; i++) {
			numberAnswerChoiceButtons[i] = new AnswerButton(i);
			numberAnswerChoiceButtons[i].addActionListener(this);
			numberAnswerChoiceButtons[i].setText(buttonLabels.substring(i, i + 1));
			answerPanel.add(numberAnswerChoiceButtons[i], c);
			c.gridy++;
		}
		return answerPanel;
	}
	
	private JPanel constructGraphicsPanel() {
		JPanel graphicsPanel = new JPanel();
		graphicsPanel.setLayout(new FlowLayout());
		return graphicsPanel;
	}
	
	private JPanel constructButtonPanel() {
		JPanel buttonPanel = new JPanel();
		buttonPanel.setLayout(new GridLayout(1, 3));
		
		ImageIcon numberImage = provider.getScaledImage(ChildrenResource.imageNumber1, 0.80f);
		
		imageAnswerChoiceButtons = new AnswerButton[3];
		for (int i = 0; i < 3; i++) {
			imageAnswerChoiceButtons[i] = new AnswerButton(i);
			imageAnswerChoiceButtons[i].setIcon(numberImage);
			imageAnswerChoiceButtons[i].addActionListener(this);
			buttonPanel.add(imageAnswerChoiceButtons[i]);
			//c.gridy++;
		}
		return buttonPanel;
	}
	
	// Called from the controller to advance to the next question
	public void displayNextQuestion(int[] possibleAnswers) {
		this.possibleAnswers = possibleAnswers;
		
		int nextQuestion = controller.getCurrentQuestionNumber();
		if (nextQuestion % 2 == 0 && nextQuestion != 10) {
			gameMode = IMAGE_MODE;
			readyToPaint = false;
			numberImageButton.setVisible(false);
			answerPanel.setVisible(false);
			graphicsPanel.setVisible(false);
			
			graphicImageButton.setVisible(true);
			buttonNumberPanel.setVisible(true);
			
			
			// update the button panel's buttons
			for (int i = 0 ; i < 3; i++) {
				int imageNumber = possibleAnswers[i];
				ImageIcon numberImage = provider.getScaledImageByNumber(imageNumber, 0.80f);
				imageAnswerChoiceButtons[i].setIcon(numberImage);
			}
			
			// update graphic image
			ImageIcon graphicImage = controller.getGraphicImage();
			graphicImageButton.setIcon(graphicImage);
		}
		else {
			gameMode = NUMBER_MODE;
			numberImageButton.setVisible(true);
			answerPanel.setVisible(true);
			graphicsPanel.setVisible(true);
			
			graphicImageButton.setVisible(false);
			buttonNumberPanel.setVisible(false);
			
			ImageIcon numberImage = controller.getNumberImage();
		    readyToPaint = false;
		    numberImageButton.setIcon(numberImage);
		    readyToPaint = true;
		}
		matchingGamePanel.revalidate();
		matchingGamePanel.repaint();
	}
	
	public void updateMessage(String message) {
		messageLabel.setText(message);
		matchingGamePanel.revalidate();
		matchingGamePanel.repaint();
	}
	
	public void actionPerformed(ActionEvent e) {
		if (e.getSource() instanceof AnswerButton) {
			AnswerButton answerButton = (AnswerButton) e.getSource();
			controller.answerButtonPressed(this, answerButton.index);
		}
		else if (e.getSource() == numberImageButton) {
			int currentQuestion = controller.getCurrentQuestionNumber();
			controller.playAudioForNumber(currentQuestion);
		}
	}
	
	private class AnswerButton extends JButton {
		private static final long serialVersionUID = 1L;
		public AnswerButton(int index) {
			super();
			this.index = index;
		}
		public int index;
	}
	
	@Override
	public boolean cleanupView() {
		
		getMainFrame().getController(NumberMatchingGameController.class)
			.endGame(false);
		
		return true;
	}
}
